#include <std.h>
#include <pio.h>
#include <type.h>
#include <dint.h>
#include <lpt.h>
#include <memory.h>

//Bios data area memory addresses
#define BDA_LPT1 0x408
#define BDA_LPT2 0x40A
#define BDA_LPT3 0x40C
#define BDA_LPT4 0x40E
kdrv lptdrv;

static struct LPT_address	{
	u16 lpt1;
	u16 lpt2;
	u16 lpt3;
	u16 lpt4;
	u8 port;
	u8 status;
	u8 control;
}LPT_address;


#define IRQ(lpt) 		(!(((inb(lpt+1))&4)>>2))
#define ERR(lpt) 		(inb(lpt+1))&8)
#define SELECT_IN(lpt) 	(inb(lpt+1))&16)
#define PAPER_OUT(lpt) 	(inb(lpt+1))&32)
#define ACK(lpt) 		(inb(lpt+1))&64)
#define BUSY(lpt) 		(!(((inb(lpt+1))&128)>>7))


#define WRITE_CONTROL(lpt,control) outb(lpt+2,control)

#define STROBE(lpt) outb(lpt+2,inb(lpt+2) & (0xff-1))
#define AULINE(lpt) outb(lpt+2,inb(lpt+2) & (0xff-2))
#define INITPR(lpt) outb(lpt+2,inb(lpt+2) & (0xff-4))
#define SELPRN(lpt) outb(lpt+2,inb(lpt+2) & (0xff-8))

#define IRQ_ENABLE(lpt) outb(lpt+2,inb(lpt+2) & 16)
#define ENABLE_BIDIR(lpt) outb(lpt+2,inb(lpt+2) & 32)

u32 send_lpt(u32 lptno,u32 val)
{
	switch(lptno)	{
		case 1:outb(LPT_address.lpt1,val);
		case 2:outb(LPT_address.lpt2,val);
		case 3:outb(LPT_address.lpt3,val);
		case 4:outb(LPT_address.lpt4,val);
		default:return -1;
	}
	return NULL;
}

void lpt()
{
	printk("\nLPT unhandled");
}

int init_lpt()
{
	u16 *lpt_ptr; 
	LPT_address.lpt1=NULL;
	LPT_address.lpt2=NULL;
	LPT_address.lpt3=NULL;
	LPT_address.lpt4=NULL;
	lpt_ptr=(u16 *)BDA_LPT1;
	if((*lpt_ptr)!=NULL && (*lpt_ptr)<0xffff)	{
		LPT_address.lpt1=*lpt_ptr;
		printk("%x ",*lpt_ptr);
	}
	lpt_ptr=(u16 *)BDA_LPT2;
	if((*lpt_ptr)!=NULL && (*lpt_ptr)<0xffff)	{
		LPT_address.lpt2=*lpt_ptr;
		printk("%x ",*lpt_ptr);
	}
	lpt_ptr=(u16 *)BDA_LPT3;
	if((*lpt_ptr)!=NULL && (*lpt_ptr)<0xffff)	{
		LPT_address.lpt3=*lpt_ptr;
		printk("%x ",*lpt_ptr);
	}
	lpt_ptr=(u16 *)BDA_LPT4;
	if((*lpt_ptr)!=NULL && (*lpt_ptr)<0xffff)	{
		LPT_address.lpt4=*lpt_ptr;
		printk("%x",*lpt_ptr);
	}
	return NULL;
}

lptdev lptdevice={
	.send_lpt=send_lpt,
};

kdrv lptdrv={
	.name="lpt",
	.init=init_lpt,
	.reset=NULL,
	.deinit=NULL,
	.device_irq=DEVICE_IRQ_UNUSED,
	.device=(void *)&lptdevice,
	.device_desc="\nu32 (*send_lpt)(u32 lptno,u32 val);",
};

__init(lpt_init,lptdrv);

